#include "EntityProperty.h"
#include "Scene.h"
#include "Regex/Regex.h"
#include "Regex/MetaLexer.h"
#include "Windows/GxWinForm.h"
#include "Windows/GxWinCommonDlg.h"
#include "Windows/GxWinApp.h"
#include "LibGL/GxUI.h"
namespace FinalRendering
{
	namespace Editor
	{
		using namespace GxRendering::UI;

		bool IsInt(const String & newVal)
		{
			PureRegex rg(L"(-)?\\d+");
			return rg.IsMatch(newVal);
		}

		bool IsFloat(const String & newVal)
		{
			PureRegex rg(L"(-)?(\\d*.)?\\d+");
			return rg.IsMatch(newVal);
		}

		EntityProperty::EntityProperty(FinalRendering::Editor::Entity *ent)
		{
			entity = ent;
			ReadOnly = false;
			Pickable = false;
		}

		void EntityProperty::PickValue()
		{
		}


		IntEntityProperty::IntEntityProperty(FinalRendering::Editor::Entity *ent, int *_val)
			: EntityProperty(ent), val(_val)
		{
		}
		
		String IntEntityProperty::GetValue()
		{
			return String(*val);
		}

		bool IntEntityProperty::SetValue(const String &newVal)
		{
			if (IsInt(newVal))
			{
				*val = newVal.ToInt();
				return true;
			}
			return false;
		}

		FloatEntityProperty::FloatEntityProperty(FinalRendering::Editor::Entity *ent, float *_val)
			: EntityProperty(ent), val(_val)
		{
		}
		
		String FloatEntityProperty::GetValue()
		{
			return String(*val);
		}

		bool FloatEntityProperty::SetValue(const String &newVal)
		{
			if (IsFloat(newVal))
			{
				*val = newVal.ToFloat();
				return true;
			}
			return false;
		}

		StringEntityProperty::StringEntityProperty(FinalRendering::Editor::Entity *ent, IString *_val)
			: EntityProperty(ent), val(_val)
		{
		}
		
		String StringEntityProperty::GetValue()
		{
			return String(val->GetString());
		}

		bool StringEntityProperty::SetValue(const String &newVal)
		{
			val->SetString(newVal.GetStrPtr());
			return true;
		}

		bool StringToVec3(const String & str, vec3 & v)
		{
			String profile = 
				L"Float = {(-)?(\\d+.)?\\d+}\n"\
				L"Comma = {,}\n"\
				L"#WhiteSpace = {\\s+}\n";
			GxMetaParser::MetaLexer lexer(profile);
			GxMetaParser::LexStream stream;
			bool succ = lexer.Parse(str, stream);
			if (!succ)
				return false;
			if (stream.Count() != 5)
				return false;
			GxMetaParser::LexStream::LinkNode * node = stream.Begin();
			if (node->Data.TypeID == 0)
				v.x = node->Data.Str.ToFloat();
			else
				return false;
			node = node->GetNext();
			if (node->Data.TypeID != 1)
				return false;
			node = node->GetNext();
			if (node->Data.TypeID == 0)
				v.y = node->Data.Str.ToFloat();
			else
				return false;
			node = node->GetNext();
			if (node->Data.TypeID != 1)
				return false;
			node = node->GetNext();
			if (node->Data.TypeID == 0)
				v.z = node->Data.Str.ToFloat();
			else
				return false;
			return true;
		}

		String Vec3ToString(const vec3 & v)
		{
			return String(v.x,3) + L"," + String(v.y,3) + L"," + String(v.z,3);
		}

		Vec3EntityProperty::Vec3EntityProperty(FinalRendering::Editor::Entity *ent, vec3 *_val)
			: EntityProperty(ent), val(_val)
		{
		}

		String Vec3EntityProperty::GetValue()
		{
			return Vec3ToString(*val);
		}

		bool Vec3EntityProperty::SetValue(const String &newVal)
		{
			return StringToVec3(newVal,*val);
		}

		ColorEntityProperty::ColorEntityProperty(FinalRendering::Editor::Entity *ent, vec3 *_val)
			: Vec3EntityProperty(ent,_val)
		{
			Pickable = true;
		}

		void ColorEntityProperty::PickValue()
		{
			GxWinGUI::ColorDialog dlg(GxWinGUI::Application::GetMainForm());
			if (dlg.ShowColor())
			{
				String newValue;
				newValue = String(GetRValue(dlg.Color)/255.0f, 3) + L"," +
					String(GetGValue(dlg.Color)/255.0f, 3) + L"," +
					String(GetBValue(dlg.Color)/255.0f, 3);
				SetValue(newValue);
				PickValueResult(newValue);
			}
		}

		EntityArrayProperty::EntityArrayProperty(FinalRendering::Editor::Entity *ent, IIntArray *_entArray)
			: entArray(_entArray), EntityProperty(ent)
		{

		}

		bool EntityArrayProperty::SetValue(const String &newVal)
		{
			return false;
		}

		String EntityArrayProperty::GetValue()
		{
			String rs;

			return rs;
		}
	}
}